//
//  CocOthAppController.m
//  GameTree
//
//  Created by BrunoCausse on 14/11/10.
//  Copyright 2010-2013 poulailler cie. All rights reserved.
//

#import "CocOthAppController.h"
#import "BC_GameTreeCategories.h"

#import "BC_Utils.h"

#import "BC_GameTreeController.h"
#import "BC_BoardController.h"

#import "BC_BrowserTreeNode.h"

#import "BC_Zoo.h"
#import "BC_ZooRequest.h"

#import "BC_Board.h"

enum {
	XMLType,
	binaryType
};

//methodes privées
@interface CocOthAppController(PrivateAPI)

- (IBAction)addPathExtensionChoice:(id)sender;

- (void)solveScriptOpenPanelDidEnd:(NSOpenPanel*)sheet;

@end

@implementation CocOthAppController
   

#pragma mark init

@synthesize urlCurrent;
@synthesize path;

- (void)awakeFromNib
{
		
	[menuForward setEnabled:NO];
	[menuBackstep setEnabled:NO];
	
	urlCurrent = nil;
	saveType = XMLType;
    
}

- (void)dealloc
{
    [theZoo release];
	[urlCurrent release];
	[path release];
    
    [super dealloc];
    
}

#pragma mark Open Save methods


- (IBAction)newTree:(id)sender
{
	//10.6
	[self setUrlCurrent:nil];
	//10.5
	[self setPath:nil];
	
	[boardController reset];
	[gameTreeController setRootWithPropertyList:nil];
}	
	
	
- (IBAction)saveTree:(id)sender
{
	
#if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5)

	if(path == nil) {
		
		[self saveAsTree:sender];
		
	} else {

		//archiving
		NSDictionary *plist = [gameTreeController propertyList];
		
		if(saveType == XMLType) {
			
			[plist writeToFile:path atomically:YES];

		} else {
			//binaryType
			NSData *data = [NSPropertyListSerialization dataFromPropertyList:plist 
																	  format:NSPropertyListBinaryFormat_v1_0
															errorDescription:nil];
			
			saveType = binaryType;
			[data writeToFile:path atomically:YES];
			
		}
	}
		
#else

		if(urlCurrent == nil) {
			
			[self saveAsTree:sender];
			
		} else {
			
			//archiving
			NSDictionary *plist = [gameTreeController propertyList];
			
			if(saveType == XMLType) {
				
				[plist writeToURL:urlCurrent atomically:YES];

			} else {
				//binaryType
				NSData *data = [NSPropertyListSerialization dataWithPropertyList:plist 
																		  format:NSPropertyListBinaryFormat_v1_0
																		 options:0
																		   error:nil];
				saveType = binaryType;
				[data writeToURL:urlCurrent atomically:YES];
				
			}
		}
			
		
#endif


}

					  

- (IBAction)saveAsTree:(id)sender
{
	savePanel = [NSSavePanel savePanel];
	[savePanel setMessage:@"You can Save Tree as XML or as Binary"];
	[savePanel setAccessoryView:accessoryView];
	//NSHomeDirectory() pour le home directory, nil pour le dernier utilisé
	
	[savePanel setExtensionHidden:NO];
	[savePanel setCanSelectHiddenExtension:NO];
    
    NSArray *AllowedFileType;
    
	if (saveType == XMLType) {
        AllowedFileType = [NSArray arrayWithObject:@"othelist"];
	} else {
        AllowedFileType = [NSArray arrayWithObject:@"coth"];
	}
    
	[savePanel setAllowedFileTypes:AllowedFileType];
	[savePanel setAllowsOtherFileTypes:NO];
	
#if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5)

	
	[savePanel beginSheetForDirectory:nil
								 file:(path == nil? @"Untitled":[path lastPathComponent])
					   modalForWindow:[gameTreeController window] 
						modalDelegate:self 
					   didEndSelector:@selector(savePanelDidEnd:returnCode:contextInfo:) 
						  contextInfo:nil];
	
#else

//	deprecated 10.6
//	[savePanel beginSheetForDirectory:nil
//								 file:(urlCurrent == nil? @"Untitled":[urlCurrent lastPathComponent])
//					   modalForWindow:[gameTreeController window] 
//						modalDelegate:self 
//					   didEndSelector:@selector(savePanelDidEnd:returnCode:contextInfo:) 
//						  contextInfo:nil];

	NSDictionary *plist = [gameTreeController propertyList];
	
	NSString *title = [[urlCurrent absoluteString] lastPathComponent];
	[savePanel setNameFieldStringValue:(urlCurrent == nil? @"Untitled":title)];

	[savePanel beginSheetModalForWindow:[gameTreeController window]
					  completionHandler:^(NSInteger result) {
						  
						  if (result == NSOKButton) {

							  [self setUrlCurrent:[savePanel URL]];

//							  if ([[[savePanel URL] pathExtension] isEqualToString:@"othelist"]) {
//								  [self setUrlCurrent:[savePanel URL]];
//							  } else 	if ([[[savePanel URL] pathExtension] isEqualToString:@"coth"]) {
//								  [self setUrlCurrent:[savePanel URL]];
//							  } else {
//								  [self setUrlCurrent:[[savePanel URL] URLByAppendingPathExtension:@"othelist"]];
//							  }
							  
							  //saving
							  if ([fileType selectedRow] == 0) {
								  //choix du XML
								  saveType = XMLType;
								  [plist writeToURL:urlCurrent atomically:YES];
							  } else {
								  //choix du binary
								  NSData *data = [NSPropertyListSerialization dataWithPropertyList:plist 
																							format:NSPropertyListBinaryFormat_v1_0
																						   options:0
																							 error:nil];
								  saveType = binaryType;
								  [data writeToURL:urlCurrent atomically:YES];
							  }
							  
							  //gere menu Open Recent
							  [[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL: urlCurrent];
						  }
					  }];
						  
							  
#endif
	
	
}

#if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5)

- (void)savePanelDidEnd:(NSSavePanel *)sheet 
			 returnCode:(int)returnCode 
			contextInfo:(void *)contextInfo
{
	if (returnCode == NSCancelButton) {
		return;
	}
	
	//archiving
	NSDictionary *plist = [gameTreeController propertyList];

	//Reading File
	
	[self setPath:[sheet filename]];
		
	// Saving
	if( [fileType selectedRow]==0){
		if(![[[sheet filename] pathExtension] isEqualToString:@"othelist"]) {
			path = [path stringByDeletingPathExtension];
			path = [path stringByAppendingPathExtension:@"othelist"];
		}
		// choix du XML
		saveType = XMLType;
		[plist writeToFile:path atomically:YES];
	} else {    
		// choix du binary
		NSData *data = [NSPropertyListSerialization dataFromPropertyList:plist 
																  format:NSPropertyListBinaryFormat_v1_0
																   errorDescription:nil];
		
		if(![[[sheet filename] pathExtension] isEqualToString:@"coth"]) {
			path = [path stringByDeletingPathExtension];
			path = [path stringByAppendingPathExtension:@"coth"];
		}
		saveType = binaryType;
		[data writeToFile:path atomically:YES];
	}
	
	//gere menu Open Recent
	[[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL: [NSURL fileURLWithPath:path]];
}
	
#endif
	

- (IBAction)openTree:(id)sender
{
	NSOpenPanel *openPanel = [NSOpenPanel openPanel];
	[openPanel setAllowsMultipleSelection:NO];
	NSArray *types = [NSArray arrayWithObjects:@"othelist", @"coth", nil];

#if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5)

	NSInteger result = [openPanel runModalForTypes:types];
	
#else
	
	[openPanel setAllowedFileTypes:types];
	NSInteger result = [openPanel runModal];

#endif
	
	if (result != NSOKButton) {
		return;
	}

	[self setUrlCurrent:[[openPanel URLs] lastObject]];
	
#if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5)
	
	[self setPath:[[openPanel filenames] lastObject]];
	
	if([[path pathExtension] isEqualToString:@"othelist"]) {
		saveType = XMLType;
	} else {
		saveType = binaryType;
	}
	
#else


	if([[urlCurrent pathExtension] isEqualToString:@"othelist"]) {
		saveType = XMLType;
	} else {
		saveType = binaryType;
	}
	
#endif
	

	//gere menu Open Recent
	[[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL: urlCurrent];

	[boardController reset];
	[gameTreeController setRootWithPropertyList:urlCurrent];
	
}

- (void)openFile:(NSString *)filename
{
	
	[self setUrlCurrent:[NSURL fileURLWithPath:filename]];


#if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5)
	
	[self setPath:filename];
	
	if([[path pathExtension] isEqualToString:@"othelist"]) {
		saveType = XMLType;
	} else {
		saveType = binaryType;
	}
	
#else
	

	if([[urlCurrent pathExtension] isEqualToString:@"othelist"]) {
		saveType = XMLType;
	} else {
		saveType = binaryType;
	}
	
#endif
	
	
	[boardController reset];
	[gameTreeController setRootWithPropertyList:urlCurrent];
}	

- (IBAction)addPathExtensionChoice:(id)sender
{
	NSButtonCell *button = [sender selectedCell];

    NSArray *AllowedFileType = nil;
    
	if ([[button title] isEqualToString:@"XML"]) {
        AllowedFileType = [NSArray arrayWithObject:@"othelist"];
	} else if([[button title] isEqualToString:@"Binary"]) {
        AllowedFileType = [NSArray arrayWithObject:@"coth"];
	}
    
    [savePanel setAllowedFileTypes:AllowedFileType];
	
//#if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5)
//	
//	if ([[button title] isEqualToString:@"XML"]) {
//		[savePanel setRequiredFileType:@"othelist"];
//	} else if([[button title] isEqualToString:@"Binary"]) {
//		[savePanel setRequiredFileType:@"coth"];
//	}
//	
//#else
//	
//	NSURL *url = [[savePanel URL] URLByDeletingPathExtension];
//	NSString *filename = [[url absoluteString] lastPathComponent];
//			
//
//	if ([[button title] isEqualToString:@"XML"]) {
//		[savePanel setNameFieldStringValue:[filename stringByAppendingPathExtension:@"othelist"]];
//	} else if([[button title] isEqualToString:@"Binary"]) {
//		[savePanel setNameFieldStringValue:[filename stringByAppendingPathExtension:@"coth"]];
//	}
//	
//#endif	
	
}

#pragma mark actions

/*
 avance d'un coup dans l'arbre
 */
- (IBAction)forward:(id)sender
{
	[gameTreeController forward];
}

- (BOOL)keyForward
{
	return [gameTreeController forward];
}

/*
 recule d'un coup dans l'arbre
 */
- (IBAction)backstep:(id)sender
{
	[gameTreeController backstep];
}

- (BOOL)keyBackstep
{
	return [gameTreeController backstep];
}

- (IBAction)copy:(id)sender
{
	NSPasteboard *pb = [NSPasteboard generalPasteboard];
	[self writeToPasteboard:pb];
}

- (IBAction)paste:(id)sender
{
	NSPasteboard *pb = [NSPasteboard generalPasteboard];
	[self readFromPasteboard:pb];
}

- (IBAction)connect:(id)sender
{
	if(theZoo == nil) {
		theZoo = [[BC_Zoo alloc] initWithAppController:self];
	} else {
		[self disconnect];
	}

}

	

#pragma mark menu methods

- (void)setEnabledMenuForward:(BOOL)enabled
{
	[menuForward setEnabled:enabled];
}
	
- (void)setEnabledMenuBackstep:(BOOL)enabled
{
	[menuBackstep setEnabled:enabled];
}

#pragma mark transfert vers Browser

- (NSString *)nameVariation:(int)sq
{
	return [gameTreeController nameVariation:sq];
}

- (NSString *)scoreVariation:(int)sq
{
	return [gameTreeController scoreVariation:sq];
}


- (void)addMove:(BC_Move *)move
{
	[gameTreeController addMove:move];
}

- (void)removeVariationAtSquare:(int)sq
{
	[gameTreeController removeVariation:sq];
}

- (void)setTag:(int)tag atSquare:(int)sq
{
	[gameTreeController setTag:tag atVariation:sq];
}

- (int)tagAtSquare:(int)sq
{
	return [gameTreeController tagAtSquare:sq];
}

- (void)addMoveAndPlay:(BC_Move *)move
{
	[gameTreeController addMoveAndPlay:move];
}

- (void)tryParseString:(NSString *)pString
{
	[gameTreeController	tryParseString:pString];
}

- (BOOL)tryParseStringFromScript:(NSString *)pString
{
    return [gameTreeController tryParseStringFromScript:pString];
}

- (void)startAnimation
{
	[menuSolve setTitle:@"Stop solve"];
	
	[gameTreeController startAnimation];
}

- (void)stopAnimation
{
	[menuSolve setTitle:@"Solve"];

	[gameTreeController stopAnimation];
}


#pragma mark transfert vers board

- (BC_Board *)board
{
    return [boardController board];
}

- (void)setBoard:(BC_Board *)newBoard
{
	[boardController setBoard:newBoard];
}

- (void)doMove:(BC_Move *)move
{
	[boardController doMove:move];
}

- (void)undoMove:(BC_Move *)move
{
	[boardController undoMove:move];
}

- (void)needsDisplay
{
	[boardController needsDisplay];
}

#pragma mark Pasteboard

- (void)writeToPasteboard:(NSPasteboard *)pb
{
	[pb declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:self];
	
	NSString *descript = [boardController descriptionForScript];
	descript = [descript stringByAppendingString:[gameTreeController descriptionPVariation]];
	
	[pb setString:descript forType:NSStringPboardType];
}

- (void)readFromPasteboard:(NSPasteboard *)pb
{
	NSArray *types = [pb types];
	if ([types containsObject:NSStringPboardType]) {
		NSString *value = [pb stringForType:NSStringPboardType];
		[gameTreeController	tryParseString:value];
	}
}

#pragma mark Zoo methods

-(void)disconnect
{
	[theZoo disconnect];
	[theZoo release];
	
	theZoo = nil;
	
}

-(void)zooDidFinishLaunching
{
//	NSLog(@"zooDidFinishLaunching");
	
	[menuConnect setTitle:@"DisConnect"];
	
	[menuSolve setEnabled:YES];
    [menuSolveScript setEnabled:YES];
	[gameTreeController setEnabledSolveButton:YES];

}

-(void)zooWillClose
{
//	NSLog(@"zooWillClose");
	
    [menuSolveScript setEnabled:NO];
	[menuSolve setEnabled:NO];
	[gameTreeController setEnabledSolveButton:NO];
	

	[menuConnect setTitle:@"Connect"];
	[self stopAnimation];

}



- (void)addVariationFromRequest:(BC_ZooRequest *)aRequest
{
	
	if([[aRequest parent] isEqualToString:[boardController descriptionForZoo]]) {

		if([aRequest cut] == 100) {
			
			if ([[aRequest parent] isEqualToString:[aRequest position]] && [aRequest depth] == [boardController n_empties]) {
				
				//addVariation principal
				[gameTreeController addPrincipalVariationFromZoo:aRequest];
										

			} else if ([aRequest depth] == [boardController n_empties]-1) {
				
				//addVariation secondaire
				[gameTreeController addOtherVariationFromZoo:aRequest];
								
			}

			
		}
	}
	
}

- (IBAction)solve:(id)sender
{
	if ([theZoo nRequests] > 0) {
		
		[theZoo aborting];
		
	} else {
				
		
		if (![boardController isEndgame] && ![boardController shouldPass]) {
		
			if ([boardController n_empties] < 40) {
				
				[theZoo search:[boardController board]];
				
			} else {
				
				NSAlert *alert = [NSAlert alertWithMessageText:@"Abuse" 
												 defaultButton:@"Sorry" 
											   alternateButton:nil 
												   otherButton:nil 
									 informativeTextWithFormat:@"for respect of moral contract, small request only"];
				
				[alert runModal];
			}
				
		}
		
	}
		
	
}

- (IBAction)solveScript:(id)sender
{
    
    NSOpenPanel *openPanel = [NSOpenPanel openPanel];
    
    [openPanel setAllowsMultipleSelection:NO];
    NSArray *types = [NSArray arrayWithObjects:@"script", nil];

#if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5)
    
    [openPanel retain];
    
    [openPanel beginForDirectory:nil
                            file:nil
                           types:types
                modelessDelegate:self
                  didEndSelector:@selector(solveScriptOpenPanelDidEnd:
                                           returnCode:
                                           contextInfo:)
                     contextInfo:nil];
    
    
    
#else
	    
    [openPanel setAllowedFileTypes:types];
    
//  [openPanel setLevel:CGShieldingWindowLevel()]; //utilité?
    
    [openPanel beginWithCompletionHandler:^(NSInteger returnCode) {
        if(returnCode == NSFileHandlingPanelOKButton) {
            [theZoo startScript:[[openPanel URLs] lastObject]];
        }
    }];

    
    
#endif
	

}

-(void)solveScriptOpenPanelDidEnd:(NSOpenPanel*)sheet
                       returnCode:(int)returnCode
                      contextInfo:(void*)contextInfo {
    
    if(returnCode != NSOKButton)
        return;
    
    [theZoo startScript:[[sheet URLs] lastObject]];
    
    [sheet release];

}

- (IBAction)liste:(id)sender
{
	[theZoo listeRequests];
}


-(void)stopZoo
{
	[theZoo aborting];
}

	
@end
